/*******************************************************************************
Homework 2: Estimate Pi
Author:Andrew Shore
Date Last Modified: February 1, 2010

Description: This program takes a Monte Carlo approach to computing Pi. The
basic idea is to throw "darts" at the unit square((0 < x < 1) & (0 < y < 1))
and to keep track of how many land inside the upper right quarter of the unit
disk(x^2 + y^2 <= 1). The ratio of points that land in the disk over the total
number of darts thrown should be approximate to Pi/4. It consists of a main 
function and a computePi function.

The main function prompts the user for two postive integer values for how many
iterations they wish the function to repeat and a how often they want to
print the estimations of pi. The integers are checked to ensure they are 
nonegative and if they are the program displays an error message.
These integers are passed to a computePi function.

The computePi function consists primarly of a for loop that generates a 
random point in the unit square.  It then checks to see if this point is
also in the unit disk and if it is a counter is incremented.  Pi is estimated
by type casting the counter(number of points that landed in the disk) into a
double and type casting the i in the for loop(current iteration) and dividing 
the two and multiply by 4. Then if the print frequency divided by the current
iteration has a remainder of 0 then this estimation of pi is printed to the
screen. A special case is needed for i=0 because dividing by 0 prints nan 
to the screen instead of 0.

*******************************************************************************/

#include<iostream>
#include<cstdlib>
#include<cstdio>

using namespace std;

/********************************************************************************  
 *  Function to estimatePi:
 *
 *  We run a loop and generate random numbers inside the unit square checking 
 *  to see if it is also in the unit circle.  Pi is estimated by dividing all
 *  the points by the ones that land in the circle. Prints every multiple of
 *  printFrequency
 *
 *  Parameters:
 *     numberOfIterations - how many times the for loop will run, user specified
 *     printFrequency - how often the estimates of pi will be printed    
 *  Output: none except output to the screen or log file
**/
void computePi(int numberOfIterations, int printFrequency){
 
  /* Variables: 
   * counter - used to keep track of how many points land in the unit disk
   * randomX,randomY - generates a random point in the unit square
   * pi - estimation of pi
   * srand(time(NULL)) - intializes random number generator
   * FOUR - constant to be used in computing pi, avoids magic numbers
  **/
  int counter = 0;
  double pi = 0;
  double randomX;
  double randomY;
  srand(time(NULL));
  enum {FOUR = 4};

  // formatted print, columns 15 spaces across, prints the top of the table
  printf("%-15s %-15s %-15s \n", "Iteration", "Darts hit", "Pi");
 
  /*for loop, iterates until i reaches a user specified number of iterations,
   * each iteration produces a random double between 0 and 1, checks to see 
   * if that point is in the semicircle and estimates pi and prints it to the 
   * screen when the print frequency comes up
  **/
  for(int i = 0; i <= numberOfIterations; i++){

    //generates random point in unit square
    randomX = rand() / static_cast<double>(RAND_MAX);
    randomY = rand() / static_cast<double>(RAND_MAX);
       
    //type casting two ints to be used in computing pi
    double dartsHit   = static_cast<double>(counter);
    double totalDarts = static_cast<double>(i);   
   
    
    
    /*if statement is executed if the current iteration is divisble by the
      printFrequency and if it is it prints out the current iterations, how
      many 'darts' hit the circle, and the approximation of pi    
    */
    if( i % printFrequency == 0){
      /* estimation of pi:
      checks to see if totalDarts(aka current iteration) is 0 so there is no
      divide by 0 error, else computes pi
      */
      if(totalDarts == 0){
        pi=0;
      }
      else{
        pi = FOUR * (dartsHit / totalDarts);
      }

      /* formatted print, columns 15 spaces across, prints the current
        iteration, how many points lie in the unit disk, and the 
        current estimation of pi
      */
      printf("%-15i %-15i %-15f \n", i,counter, pi);
     

    }
    
      
    //if the point is in the circle(i.e. x^2+y^2<=1) then counter is incremented
    if( (randomX)*(randomX) + (randomY)*(randomY) <= 1){
      counter++;
    }
    
  } 
printf("%s %f \n", "The approximate value of 'pi' is  ", pi);
  
}

int main(){

  //Variables passed to computePi function
  int numberOfIterations;
  int printFrequency;
 
  cout << "Welcome to the Estimate Pi Program. \n";

  
  /*  Asks user to input number of times they wish the function to iterate,
      higher iterations have a higher probability of being more accurate
  */
  cout << "Please enter a postive number for the number of"
       << " iterations you wish to use. \n";
  
  cin >> numberOfIterations;
  
    //checks if numberOfIterations is positive
    if(numberOfIterations < 0){
     
      cout << "ERROR: Please enter a postive number of iterations \n";
      return 0;
    }
   
  
  
  
  //  Asks user how often they want to print the estimates of pi.
  cout << "Thank you, now please enter the frequency at which you wish\n"
       << "to print the estimates of Pi. \n";

  cin  >> printFrequency;
  
    //checks if printFrequency is positive
    if(printFrequency < 0){
     
      cout << "ERROR: Please enter a positive print frequency\n";
      return 0;
    } 
   
    
   
 

  cout << "We approximate 'pi' with "  << numberOfIterations << " iterations\n";
  cout << "We print the current approximation every "
       << printFrequency << " iterations \n";
 
  //calls computePi function with two integer parameters
  computePi(numberOfIterations, printFrequency);
 
  

  return 0;



}

